/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package paperlessflat.helper;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.Hashtable;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author thunder2002
 */
public class Converter {
    private static Hashtable<String, Method> converters;
    
    static {
        converters = new Hashtable<String, Method>();
        Method[] methods = Converter.class.getDeclaredMethods();
        
        String paramName;
        String returnName;
        Class<?>[] paramTypes;
        for (Method method : methods) {
            paramTypes = method.getParameterTypes();
            if (paramTypes.length == 1) {
                paramName = paramTypes[0].getName();
                returnName = method.getReturnType().getName();
                converters.put(paramName + returnName, method);
            }
        }
    }
    
    private Converter() {        
    }
    
    public static <T> T convert(Object obj, Class<T> clazz) {
        if (obj == null)
            return null;
        
        Class<?> objClazz = obj.getClass();
        
        if (clazz.isAssignableFrom(objClazz))
            return (T)obj;
        
        String converterName = objClazz.getName() + clazz.getName();
        Method converterMethod = converters.get(converterName);
        if (converterMethod != null)
        {
            try {
                return (T)converterMethod.invoke(clazz, new Object[] { obj });
            } catch (Exception ex) {
                throw new RuntimeException(String.format(
                        "Convertion from '%s' to '%s' failed", objClazz.getName(), clazz.getName()));
            }
        }
        
        throw new UnsupportedOperationException(String.format(
                "Cannot convert from '%s' to '%s'", objClazz.getName(), clazz.getName()));
    }
    
    // Converters ---------------------------------------------------------------------------------

    /**
     * Converts Integer to Long.
     * @param value The Integer to be converted.
     * @return The converted Long value.
     */
    public static Long integerToLong(Integer value) {
        return new Long(value.longValue());
    }

    /**
     * Converts Long to Integer.
     * @param value The Integer to be converted to Long.
     * @return The converted Long value of the Integer.
     */
    public static Integer longToInteger(Long value) {
        return new Integer(value.intValue());
    }

    /**
     * Converts Integer to Boolean. If integer value is 0, then return FALSE, else return TRUE.
     * @param value The Integer to be converted.
     * @return The converted Boolean value.
     */
    public static Boolean integerToBoolean(Integer value) {
        return value.intValue() != 0 ? new Boolean(true) : new Boolean(false);
    }

    /**
     * Converts Boolean to Integer. If boolean value is TRUE, then return 1, else return 0.
     * @param value The Boolean to be converted.
     * @return The converted Integer value.
     */
    public static Integer booleanToInteger(Boolean value) {
        return value.booleanValue() ? new Integer(1) : new Integer(0);
    }

    /**
     * Converts Double to BigDecimal.
     * @param value The Double to be converted.
     * @return The converted BigDecimal value.
     */
    public static BigDecimal doubleToBigDecimal(Double value) {
        return new BigDecimal(value.doubleValue());
    }

    /**
     * Converts BigDecimal to Double.
     * @param value The BigDecimal to be converted.
     * @return The converted Double value.
     */
    public static Double bigDecimalToDouble(BigDecimal value) {
        return new Double(value.doubleValue());
    }

    /**
     * Converts Integer to String.
     * @param value The Integer to be converted.
     * @return The converted String value.
     */
    public static String integerToString(Integer value) {
        return value.toString();
    }

    /**
     * Converts String to Integer.
     * @param value The String to be converted.
     * @return The converted Integer value.
     */
    public static Integer stringToInteger(String value) {
        return new Integer(value);
    }
    
    public static Float stringToFloat(String value) {
        return new Float(value);
    }

    /**
     * Converts Boolean to String.
     * @param value The Boolean to be converted.
     * @return The converted String value.
     */
    public static String booleanToString(Boolean value) {
        return value.toString();
    }

    /**
     * Converts String to Boolean.
     * @param value The String to be converted.
     * @return The converted Boolean value.
     */
    public static Boolean stringToBoolean(String value) {
        return new Boolean(value);
    }

    /**
     * Converts char array to String.
     * @param value The char array to be converted.
     * @return The converted String.
     */
    public static String charsToString(char[] value) {
        return new String(value);
    }
    
    /**
     * Converts String to char array.
     * @param value The String to be converted.
     * @return The converted char array.
     */
    public static char[] stringToChars(String value) {
        return value.toCharArray();
    }
}
